/*
Copyright DAUPHIN Maxime 2005

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
http://www.gnu.org/licenses/gpl.txt
*/
#include "ClipBoard.h"
#include "Wnd.h"
#include "Bitmap.h"

namespace Gui {

/** Constructor */
ClipBoard::ClipBoard(void)
{
	m_bDisableNext = false;
}

ClipBoard::~ClipBoard(void)
{
	assert( m_pWnd );
	::ChangeClipboardChain( *m_pWnd, m_hWndNextViewer); 
}

void ClipBoard::create(Wnd *pWnd)
{
	assert( pWnd );
	m_pWnd = pWnd;
	m_hWndNextViewer = ::SetClipboardViewer( *m_pWnd ); 
}

Any ClipBoard::onDrawClipBoard(UINT &uFormat)
{
	if ( m_bDisableNext )
	{
		m_bDisableNext = false;
		uFormat = 0;
		return Any( STRING("Skip Next") );
	}

	assert( m_pWnd );
	//STRING ret = _T("Error");
	if ( ::OpenClipboard( *m_pWnd )) 
    {
		uFormat = enumClipboardFormats(0);
		while ( uFormat )
		{
			switch ( uFormat )
			{
			case CF_OWNERDISPLAY:
				break;
			case CF_TEXT:
				{
					HGLOBAL hglb = ::GetClipboardData(uFormat);
					if ( !hglb ) 
					{
						::CloseClipboard();
						//return _T("");
						return Any( STRING("Error") );
					}
					
					LPSTR lpstr = (LPSTR)::GlobalLock(hglb); 
					
					std::string ret = conversion(lpstr);
					::GlobalUnlock(hglb); 
					::CloseClipboard();
					return Any( (std::string)ret );
				}
			case CF_BITMAP:
				{
					Bitmap bmp;
					bmp.create( (HBITMAP) ::GetClipboardData(uFormat) );
					::CloseClipboard();
					return Any( bmp );
				}
			case CF_HDROP: //A handle to type HDROP that identifies a list of files
				{
					HDROP hDrop = (HDROP)::GetClipboardData(uFormat);
					DropFile drop;
					drop.create(hDrop);
					::CloseClipboard();
					return Any( drop );
					/*
					assert(hDrop);
					//Retreive Number of file
					UINT num = ::DragQueryFile( hDrop, 0xFFFFFFFF, NULL, 0 );
					for ( UINT i = 0; i < num; i++ )
					{
						//retrieve filename size
						UINT size = ::DragQueryFile( hDrop, 0, NULL, 0 );
						char *pFileName = new char[size+1];
						UINT ret = ::DragQueryFile( hDrop, 0, pFileName, size+1 );
						int toDel = 0;
					}
					*/
				}
			}
		uFormat = enumClipboardFormats(uFormat);
		}
	}
	return Any( STRING("ClipBoard Format unknown") );
}

UINT ClipBoard::enumClipboardFormats(UINT uFormat)
{
	return ::EnumClipboardFormats(uFormat);
}

HANDLE ClipBoard::setClipboardData(UINT uFormat, HANDLE hMem)
{
	assert( m_pWnd );
	//STRING ret = _T("Error");
	assert( ::OpenClipboard( *m_pWnd ) == TRUE );
	HANDLE hRet = ::SetClipboardData( uFormat, hMem );
	assert( hRet );
	assert( ::CloseClipboard() );
	return hRet;
}

bool ClipBoard::setData( uint uFormat, const Any &any )
{
	HANDLE hGlobal;
	bool ok = false;
	switch (uFormat)
	{
		case CF_TEXT :
		{
			STRING str = any_cast<STRING>((Any)any);
			hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, str.size()+1);
			char *ptr = (char *)GlobalLock(hGlobal);
			strcpy( ptr, str.c_str() );
			ok = true;
			break;
		}

		case CF_BITMAP :
		{
			Bitmap bitmap = any_cast<Bitmap>((Any)any);
			//hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, str.size()+1);
			hGlobal = bitmap.getSafeHandle();
			ok = true;
			break;
		}

		case CF_HDROP :
		{
			// TODO : unicode management 
			DropFile drop = any_cast<DropFile>((Any)any);

			//get all file list separte by 0
			STRING files = drop.getFiles();
			DROPFILES dobj = { 20, { 0, 0 }, 0, 0 };

			size_t nLen = files.size();

			int nGblLen = sizeof(dobj) + (int)nLen + 5;
			HGLOBAL hGbl = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, nGblLen);
			char* sData = (char*)::GlobalLock(hGbl);
			memcpy( sData, &dobj, sizeof(DROPFILES) );
			char* sWStr = sData+sizeof(DROPFILES);
			memcpy( sWStr, files.c_str(), nLen );
			ok = true;
			break;
		}
	}
	if ( ok )
	{
		//::GlobalUnlock(hGlobal);
		disableNext(); //Skip this item
		assert( ::OpenClipboard( *m_pWnd ) == TRUE );
		::EmptyClipboard();
		::SetClipboardData( uFormat, hGlobal );
		::CloseClipboard();
		return true;
	}
	return false;
}

void ClipBoard::disableNext(void)
{
	m_bDisableNext = true;
}

} //End namespace Gui

